package ansible


import (
	db "hulk-api/databases"
	"log"
	"hulk-api/util/command"
	"strings"
	"fmt"
	"sync"
	"time"
)

type IpAddress struct {
	Ip string			`json:"ip"`
}

type HostGroup struct {
	Name string			`json:"name"`
	IpList string 		`json:"iplist"`
}


type TemplatePath struct {
	Name string			`json:"name"`
	Path string 		`json:"path"`
}

func (ip IpAddress) GetLists() ( ips []IpAddress, err error) {

	//sql := fmt.Sprintf(" select account,name,email,department,role,lastLoginTime from user")
	rows, err := db.SqlDB.Query("select ip from assets")
	defer rows.Close()

	for rows.Next() {
		var i IpAddress
		rows.Scan(&i.Ip)
		ips = append(ips, i)
	}
	if err = rows.Err(); err != nil {
		return
	}
	return
}


func (h HostGroup) GetHosts() ( hosts []HostGroup, err error) {

	//sql := fmt.Sprintf(" select account,name,email,department,role,lastLoginTime from user")
	rows, err := db.SqlDB.Query("select item,ips from hosts")
	defer rows.Close()

	for rows.Next() {
		var hh HostGroup
		rows.Scan(&hh.Name,&hh.IpList)
		hosts = append(hosts, hh)
	}
	if err = rows.Err(); err != nil {
		return
	}
	return
}

func (h HostGroup) UpdateHosts() (  err error) {
	stmt, err := db.SqlDB.Prepare("update hosts set ips=? where item=?")
	defer stmt.Close()
	if err != nil {
		log.Println(err)
		return
	}
	_, err = stmt.Exec(h.IpList, h.Name)
	if err != nil {
		log.Println(err)
		return
	}
	return
}

func (h HostGroup) Add() (  err error) {
	stmt, err := db.SqlDB.Prepare("insert into hosts(item,ips) values(?,?)")
	if err != nil {
		return
	}
	defer stmt.Close()
	_, err = stmt.Exec(h.Name, h.IpList)
	if err != nil {
		return
	}
	return
}


func (t TemplatePath) GetPath() (  templates []TemplatePath, err error) {

	//sql := fmt.Sprintf(" select account,name,email,department,role,lastLoginTime from user")
	rows, err := db.SqlDB.Query("select name,path from template where ref='ansible'")
	defer rows.Close()
	for rows.Next() {
		var tt TemplatePath
		rows.Scan(&tt.Name,&tt.Path)
		templates = append(templates, tt)
	}
	if err = rows.Err(); err != nil {
		return
	}
	return

}

//hosts 远程

type Module struct {
	Name string 			`json:"name"`
	IpLine string			`json:"ipLine"`
	IpList []string
	Param string			`json:"param"`
	CmdLine []string
}

func (m *Module) setCmdLines()  {
	if len(m.CmdLine) > 0 {
		return
	}
	for _,ip := range strings.Split(m.IpLine,",") {
		m.IpList = append(m.IpList,ip)
		line := fmt.Sprintf("ansible %s -m %s '%s'" , ip , m.Name , m.Param)
		m.CmdLine = append(m.CmdLine,line)
	}

}

func (m *Module) Run() string {
	time.Sleep(3 * time.Second)  //test
	m.setCmdLines()
	output := ""

	num := len(m.CmdLine)
	wg := sync.WaitGroup{}
	wg.Add(num)
	outputChan := make(chan string,num)
	//defer close(outputChan)

	for _,line := range m.CmdLine {
		c,_ := NewAnsibleCmd(line)
		go c.Run(&wg,outputChan)
	}
	wg.Wait()

	close(outputChan)  //必须先关闭，否则for range 会出现非检测 dead lock ， 一直堵塞也不报错
	for res := range outputChan {
		output = output + res
	}

	return output
}

func   NewAnsibleCmd(line string)(*command.Command,error)   {
	//var c *command.Command
	c := &command.Command{}
	c.CmdLine = line
	return command.NewCmd(c)
}

